home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / choices / chcssml1.lha / Clock.c < prev    next >
C/C++ Source or Header  |  1989-02-06  |  4KB  |  173 lines

  1. /*
  2.  * This file is part of the Choices Operating System Simulator
  3.  * Developed by: The TAPESTRY Parallel Computing Laboratory
  4.  *         University of Illinois at Urbana-Champaign
  5.  *         Department of Computer Science
  6.  *         1304 W. Springfield Ave.
  7.  *         Urbana, IL    61801
  8.  *
  9.  * Copyright (c) 1987, 1988, 1989 The University of Illinois Board of Trustees.
  10.  *    All Rights Reserved.
  11.  * CONFIDENTIAL INFORMATION. Distribution restricted under license agreement.
  12.  *
  13.  * Author: Gary M. Johnston (johnston@cs.uiuc.edu)
  14.  * Project Manager and Principal Investigator: Roy Campbell (roy@cs.uiuc.edu)
  15.  *
  16.  * Funded by: NSF TAPESTRY Grant No. 1-5-30035, NASA ICLASS Grant 
  17.  *   No. 1-5-25469 and No. NSG1471 and AT&T Metronet Grant No. 1-5-37411.
  18.  */
  19. /*
  20.  * Clock.c - Microtimeslicing.
  21.  *
  22.  *    $Header: Clock.c,v 1.4 88/02/16 10:59:31 johnston Exp $
  23.  *    $Locker: johnston $
  24.  */
  25.  
  26. #include "Assert.h"
  27. #include "Debug.h"
  28. #include "Clock.h"
  29. #include "Print.h"
  30. #include "Process.h"
  31. #include "Signal.h"
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <sys/time.h>
  35. #include <task.h>
  36.  
  37. extern int setitimer( int, itimerval *, itimerval * );
  38. extern int sigsetmask( int );
  39.  
  40. const int Timer =    ITIMER_VIRTUAL;    // Virtual process time timer.
  41. const int Signal =   SIGVTALRM;        // Signal sent upon timer expiration.
  42. const int Mask =     sigmask(Signal);    // Signal as a mask.
  43. const int Interval = 10000;        // Microtimeslicing interval.
  44.  
  45. static inline int
  46. Blocked( int mask )
  47. {
  48.     /*
  49.      * Return non-zero iff the signals in mask are currently blocked.
  50.      */
  51.     return (sigblock(0) & mask);
  52. }
  53.  
  54. int
  55. IsAProcessTask( task * t )
  56. {
  57.     /*
  58.      * Return non-zero iff the task is a ProcessTask.
  59.      *
  60.      * WARNING: This method of figuring out whether or not a task is
  61.      *        a ProcessTask is disgusting.
  62.      */
  63.     if ( t == 0 )
  64.         return(0);
  65.     const char * const name = "ProcessTask";
  66.     const int length = 11;
  67.     return ( strncmp( t->t_name, name, length ) == 0 );
  68. }
  69.  
  70. static void
  71. ClockHandler( int sig, int code, Sigcontext * scp )
  72. {
  73.     /*
  74.      * UNIX signal handler.
  75.      * The basic job is to microtimeslice preemptable ProcessTasks.
  76.      */
  77.     Assert(sig == Signal);
  78.     Assert(code == 0);
  79.     Assert(scp != 0);
  80.  
  81.     /*
  82.      * Unblock the Signal.
  83.      * It's automatically blocked when the Signal is delivered.
  84.      * We have to do this before we might delay, because
  85.      * the delay would relinquish.
  86.      */
  87.     Assert(Blocked(Mask));
  88.     sigsetmask(0);
  89.  
  90.     /*
  91.      * If the current task is a ProcessTask and is preemptable,
  92.      * then delay it (i.e., microtimeslice ended).
  93.      * Otherwise, let it continue.
  94.      */
  95.     if ( IsAProcessTask( thistask ) ) {
  96.         ProcessTask * p = (ProcessTask *) thistask;
  97.         if ( p->setPreemptable( 0 ) ) {
  98.             Debug("ClockHandler: %s delay.\n", p->t_name);
  99.             //Print(".");
  100.             p->delay(1);
  101.             p->setPreemptable(1);
  102.             Assert(!Blocked(Mask));
  103.             return;
  104.         }
  105.         Debug("ClockHandler: %s no delay.\n", p->t_name);
  106.         Assert(!Blocked(Mask));
  107.         return;
  108.     }
  109.     Debug("ClockHandler: %s continue.\n", thistask->t_name);
  110.     Assert(!Blocked(Mask));
  111. }
  112.  
  113. void
  114. StartClock()
  115. {
  116.     /*
  117.      * Arrange for ClockHandler() to catch the Timer Signals
  118.      * and then start the Timer.  The Timer is set to automatically
  119.      * reset itself, so we don't have to restart it each time it expires.
  120.      * This makes ClockHandler simpler and quicker.
  121.      */
  122.  
  123.     /*
  124.      * Aim Signal at ClockHandler.
  125.      */
  126.     Sigvec vec;
  127.     vec.sv_handler = ClockHandler;
  128.     vec.sv_mask = 0;
  129.     vec.sv_onstack = 0;
  130.     if ( sigvec( Signal, &vec, (Sigvec *) 0 ) != 0 ) {
  131.         perror("StartClock: sigvec");
  132.         exit(1);
  133.     }
  134.  
  135.     /*
  136.      * Start the Timer.
  137.      */
  138.     itimerval value;
  139.     const int sec = Interval / 1000000;
  140.     const int usec = Interval % 1000000;
  141.     value.it_interval.tv_sec = sec;
  142.     value.it_interval.tv_usec = usec;
  143.     value.it_value.tv_sec = sec;
  144.     value.it_value.tv_usec = usec;
  145.     if ( setitimer( Timer, &value, (itimerval *) 0 ) != 0 ) {
  146.         perror("StartClock: setitimer");
  147.         exit(1);
  148.     }
  149.  
  150.     Assert(!Blocked(Mask));
  151. }
  152.  
  153. int
  154. BlockClock()
  155. {
  156.     /*
  157.      * Block Timer Signals.
  158.      * Return previous mask.
  159.      */
  160.     Assert(sigblock(0) == 0);
  161.     return (sigblock(Mask));
  162. }
  163.  
  164. void
  165. UnblockClock( int mask )
  166. {
  167.     /*
  168.      * Restore previous mask.
  169.      */
  170.     Assert(mask == 0);
  171.     sigsetmask(mask);
  172. }
  173.